package com.pig4cloud.pig.ads.service.media;

import com.alibaba.fastjson.JSON;
import com.baidu.dev2.api.sdk.common.ApiRequestHeader;
import com.baidu.dev2.api.sdk.manual.oauth.api.OAuthService;
import com.baidu.dev2.api.sdk.manual.oauth.model.*;
import com.baidu.dev2.api.sdk.manual.oauth.model.UserInfo;
import com.baidu.dev2.api.sdk.mccfeed.api.MccFeedService;
import com.baidu.dev2.api.sdk.mccfeed.model.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dy.sdk.model.request.bd.oauth.GetUserInfoExRequset;
import com.google.api.client.util.Lists;
import com.pig4cloud.pig.ads.service.*;
import com.pig4cloud.pig.api.dto.AdAccountResp;
import com.pig4cloud.pig.api.entity.*;
import com.pig4cloud.pig.api.vo.AdAccountAgentVo;
import com.pig4cloud.pig.common.core.constant.enums.PlatformTypeEnum;
import com.pig4cloud.pig.common.core.util.R;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author chengang
 * @Date 2022/12/13
 */
@Component
public abstract class AbstractMediaEngine implements MediaEngine {

	@Autowired
	protected AdOauthSettingService oauthSettingService;
	@Autowired
	private AdAccountService adAccountService;
	@Autowired
	private AdAgentService adAgentService;
	@Autowired
	private AdvertiserService advertiserService;
	@Autowired
	private AdAccesstokenService adAccesstokenService;

	private static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd").toFormatter();

    private Logger logger = LoggerFactory.getLogger(AbstractMediaEngine.class);

	/**
	 * 处理AccessToken之后的公共逻辑，如 ad_account\代理商绑定等
	 */
	protected void saveAccessToken(AdAccesstoken adAccesstoken){
		AdAccesstoken adAccessTokenDb = adAccesstokenService.getOne(Wrappers.<AdAccesstoken>lambdaQuery()
				.eq(AdAccesstoken::getAccountId, adAccesstoken.getAccountId())
				.eq(AdAccesstoken::getMediaCode, PlatformTypeEnum.BD.getValue())
				.eq(AdAccesstoken::getDeleted, 0).last("LIMIT 1"));
		if (Objects.isNull(adAccessTokenDb)){
			adAccesstokenService.save(adAccesstoken);
		}else{
			Date date = new Date();
			adAccessTokenDb.setAccessToken(adAccesstoken.getAccessToken());
			adAccessTokenDb.setRefreshToken(adAccesstoken.getRefreshToken());
			adAccessTokenDb.setExpiresIn(adAccesstoken.getExpiresIn());
			adAccessTokenDb.setRefreshexpiresIn(adAccesstoken.getRefreshexpiresIn());
			adAccessTokenDb.setExpiresTime(adAccesstoken.getExpiresTime());
			adAccessTokenDb.setRefreshexpiresTime(adAccesstoken.getRefreshexpiresTime());
			adAccessTokenDb.setOpenId(adAccesstoken.getOpenId());
			adAccessTokenDb.setAdvertiserIds(adAccesstoken.getAdvertiserIds());
			adAccessTokenDb.setUpdateId(adAccesstoken.getUpdateId());
			adAccessTokenDb.setTokenTime(date);
			adAccessTokenDb.setUpdateTime(date);
			adAccesstokenService.updateById(adAccessTokenDb);
		}
	}

	//1.获取账户列表
	protected AdAccountResp getAdvertiser(GetAccessTokenResponse accessTokenInfo, List<AdAccountAgentVo.Advertiser> advertisers) {
		// 考虑账户管家变更的情况，参考其他渠道的加挂逻辑
		AdAccountResp housekeeperInfo = new AdAccountResp();
		try {
			AccessTokenInfo accessToken = accessTokenInfo.getData();
			OAuthService oAuthService = new OAuthService();
			GetUserInfoExRequset request = new GetUserInfoExRequset();
			request.setAccessToken(accessToken.getAccessToken());
			request.setUserId(accessToken.getUserId());
			request.setOpenId(accessToken.getOpenId());
			request.setNeedSubList(true);
			// 上一页返回的最大userid，用于子账号列表分页 子账号大于500需要分页，目前分析不会大于500，暂时不做分页处理
			request.setLastPageMaxUcId(1);
			request.setPageSize(500);
			logger.info(">>>查询授权用户信息param:{}", JSON.toJSONString(request));
			GetUserInfoResponse response = oAuthService.getUserInfo(request);
			logger.info(">>>查询授权用户信息result:{}", JSON.toJSONString(response));
			if (null != response && null != response.getData() && 0 == response.getCode()) {
				housekeeperInfo.setAdvertiserId(response.getData().getMasterUid().toString());
				housekeeperInfo.setAdvertiserName(response.getData().getMasterName());
				List<SubUserInfo> userInfo = response.getData().getSubUserList();
				if (CollectionUtils.isNotEmpty(userInfo)) {
					for (SubUserInfo subUserInfo : userInfo) {
						AdAccountAgentVo.Advertiser advertiser = new AdAccountAgentVo.Advertiser();
						advertiser.setAdvertiserId(String.valueOf(subUserInfo.getUcId()));
						advertiser.setAdvertiserName(subUserInfo.getUcName());
						advertisers.add(advertiser);
					}
				}
			}
		} catch (Exception e) {
			logger.error("获取账户列表异常：{}", e);
		}
		return housekeeperInfo;
	}

	//3.处理代理商 --公共逻辑
	protected String saveAgent(List<AdAccountAgentVo.Advertiser> advertisers, Integer userId, Integer agentId) {
		if (Objects.isNull(agentId)){
			return "OK";
		}
		// 为广告账户设置代理
		AdAgent agent = adAgentService.getOne(Wrappers.<AdAgent>lambdaQuery().select(AdAgent::getAgentName).eq(AdAgent::getId, agentId).eq(AdAgent::getIsDelete, 0));
		if (null == agent) {
			return "OK";
		}
		AdAccountAgentVo adAccountAgentVo = new AdAccountAgentVo();
		adAccountAgentVo.setAgentId(String.valueOf(agentId));
		adAccountAgentVo.setAgentName(agent.getAgentName());
		adAccountAgentVo.setEffectiveTime(LocalDate.now().format(DATE_FORMATTER));
		adAccountAgentVo.setAdvertisers(advertisers);
		List<String> list = adAccountService.batchAddAccountAgent(adAccountAgentVo, userId);
		return "OK";
	}

	protected void saveAdAccount(List<AdAccountAgentVo.Advertiser> list, AdAccountResp housekeeperInfo, String mediaCode) {
		List<AdAccount> addAccountList = Lists.newArrayList();
		String housekeeper = housekeeperInfo.getAdvertiserId();
		// 已经加挂的广告账户
		QueryWrapper<AdAccount> wrapper = new QueryWrapper<>();
		wrapper.eq("media_code", mediaCode);
		wrapper.eq("is_delete", 0);
		List<AdAccount> accountsList = adAccountService.list(wrapper);
		List<String> adIdList = new ArrayList<>();
		for (AdAccountAgentVo.Advertiser advertiser : list) {
			String advertiserId = String.valueOf(advertiser.getAdvertiserId());
			String advertiserName = String.valueOf(advertiser.getAdvertiserName());
			adIdList.add(advertiserId);

			// 验证账户是否已经加挂
			List<AdAccount> accounts = accountsList.stream().filter(v -> v.getAdvertiserId().equals(advertiserId)).collect(Collectors.toList());
			if (CollectionUtils.isEmpty(accounts)) {
				AdAccount adAccount = new AdAccount();
				adAccount.setMediaCode(mediaCode);
				adAccount.setMediaName(PlatformTypeEnum.descByValue(mediaCode));
				adAccount.setAdvertiserId(advertiserId);
				adAccount.setAdvertiserName(advertiserName);
				adAccount.setHousekeeper(housekeeper);
				adAccount.setEffectiveStatus(1);
				adAccount.setCreateTime(new Date());
				addAccountList.add(adAccount);
			} else {
				AdAccount adAccount = accounts.get(0);
				adAccount.setAdvertiserName(advertiserName);
				adAccount.setHousekeeper(housekeeper);
				adAccount.setEffectiveStatus(1);
				adAccount.setUpdateTime(new Date());
				addAccountList.add(adAccount);
			}
		}

		accountsList.forEach(acc -> {
			// 验证是否属于本次加挂的账户 ， 如果不是生效状态设置为：失效
			List<AdAccountAgentVo.Advertiser> advertiserList = list.stream().filter(v -> v.getAdvertiserId().equals(acc.getAdvertiserId())).collect(Collectors.toList());
			if (CollectionUtils.isEmpty(advertiserList)){
				acc.setEffectiveStatus(2);
				acc.setUpdateTime(new Date());
				addAccountList.add(acc);
			}
		});

		if (CollectionUtils.isEmpty(accountsList.stream().filter(v -> v.getAdvertiserId().equals(housekeeper)).collect(Collectors.toList()))){
			// 保存管家账户信息
			AdAccount adAccount = new AdAccount();
			adAccount.setMediaCode(mediaCode);
			adAccount.setMediaName(PlatformTypeEnum.descByValue(mediaCode));
			adAccount.setAdvertiserId(housekeeper);
			adAccount.setAdvertiserName(housekeeperInfo.getAdvertiserName());
			adAccount.setHousekeeper(housekeeper);
			adAccount.setEffectiveStatus(1);
			adAccount.setCreateTime(new Date());
			addAccountList.add(adAccount);
		}

		if (CollectionUtils.isNotEmpty(addAccountList)) {
			adAccountService.saveOrUpdateBatch(addAccountList, 1000);
		}
	}

	protected void saveAdvertiser(List<AdAccountAgentVo.Advertiser> list, AdAccountResp housekeeperInfo, String mediaCode) {
		List<Advertising> saveAdvertiserList = Lists.newArrayList();
		String housekeeper = housekeeperInfo.getAdvertiserId();
		// 已经加挂的广告账户
		QueryWrapper<Advertising> wrapper = new QueryWrapper<>();
		wrapper.eq("platform_id", mediaCode);
		wrapper.eq("deleted", 0);
		List<Advertising> advertiserList = advertiserService.list(wrapper);
		List<String> adIdList = new ArrayList<>();
		for (AdAccountAgentVo.Advertiser advertiser : list) {
			String advertiserId = String.valueOf(advertiser.getAdvertiserId());
			String advertiserName = String.valueOf(advertiser.getAdvertiserName());
			BigDecimal balance = new BigDecimal("0");
			adIdList.add(advertiserId);
			// 验证账户是否已经加挂
			List<Advertising> accounts = advertiserList.stream().filter(v -> v.getAdvertiserId().equals(advertiserId)).collect(Collectors.toList());
			if (CollectionUtils.isEmpty(accounts)) {
				Advertising ttAdvertiser = new Advertising();
				ttAdvertiser.setPlatformId(Integer.valueOf(mediaCode));
				ttAdvertiser.setAdvertiserId(advertiserId);
				ttAdvertiser.setName(advertiserName);
				ttAdvertiser.setBalance(balance);
				ttAdvertiser.setHousekeeper(housekeeper);
				ttAdvertiser.setCreatetime(new Date());
				saveAdvertiserList.add(ttAdvertiser);
			} else {
				Advertising ttAdvertiser = accounts.get(0);
				ttAdvertiser.setName(advertiserName);
				ttAdvertiser.setBalance(balance);
				ttAdvertiser.setHousekeeper(housekeeper);
				ttAdvertiser.setUpdatetime(new Date());
				saveAdvertiserList.add(ttAdvertiser);
			}
		}

		if (CollectionUtils.isNotEmpty(saveAdvertiserList)) {
			advertiserService.saveOrUpdateBatch(saveAdvertiserList, 1000);
		}
	}

	/**
	 * 根据媒体类型获取授权配置
	 * @param mediaCode
	 * @return
	 */
	protected AdOauthSetting getOauthSetting(String mediaCode){
		//获取所有回调配置
		List<AdOauthSetting> oauthSettingList = oauthSettingService.list(Wrappers.<AdOauthSetting>lambdaQuery().eq(AdOauthSetting::getDeleted,0));
		if (CollectionUtils.isEmpty(oauthSettingList)) {
			return null;
		}
		Map<String,AdOauthSetting> oauthSettingMap = oauthSettingList.stream()
				.collect(Collectors.toMap(AdOauthSetting::getMediaCode, Function.identity()));
		AdOauthSetting setting = oauthSettingMap.get(mediaCode);
		return setting;
	}

}
